POV-Ray : Newsgroups : povray.general : MultiMesh : MultiMesh Server Time
5 Nov 2024 10:23:22 EST (-0500)
  MultiMesh  
From: PM 2Ring
Date: 5 Sep 2005 10:55:00
Message: <web.431c5b735fa5904d43d28a00@news.povray.org>
Greetings, Raytracers!

I recently discovered a cute technique for scenes that use lots of copies of
a few similar mesh objects, for example, plants.

The problem is that if you only use a small number of mesh objects, this can
be obvious on close inspection. However, if you use too many different
meshes, then you start to lose the memory advantage that meshes give you.

My trick is to make meshes that can be overlapped on top of each other. The
simplest way to do this is to use a checker pattern. Given a pair of meshes
that can be overlapped thusly, we can create 16 different variations by
using the 8 symmetry transforms of the square. So, with just 8 base mesh
objects, we can make 256 mesh pairs. This definitely helps to disguise the
fact that the meshes are being reused. :)

Anyway, here's a simple scene to illustrate the technique. I'll post a scene
file of a patch of turf in p.b.i.

//-----------------------------------------------------------------------------

// Persistence of Vision Ray Tracer Scene Description File
// File: MultiMesh.pov
// Vers: 3.6
// Desc: Overlapping mesh test
// Date: 27 Aug 2005
// Auth: PM 2Ring
//
// Inspired by:
//
// From: Mike Williams
// Subject: Re: Optimizing scenes with nested loops.
// Date: 13 Aug 2005 05:50:19
// Message: <mfea4CA4nY$CFwvC@econym.demon.co.uk>
//
//  -f -A0.6  +AM2 +R1
//  -d +A0.1  +AM2 +R3
//

#version 3.6;

#include "colors.inc"
#include "transforms.inc"

global_settings {
  assumed_gamma 1.0
}

//scene element control
#declare subCount = 4;                         //MUST be even!
#declare patchCount = 4;

//randomizer macros
#declare R2 = seed(17);
#macro RI(A) floor(A*rand(R2)) #end           //Random integer between 0 &
<A

//-----------------------------------------------------------------------------

//Convert UV coordinates to hue & thence to RGB
#macro GetColour(U,V)
  #local H = 720*(floor(V/2)+floor(U/2)/subCount)/subCount;
  CHSV2RGB(<H, 1, 1>)
#end

// Create a square pyramid as a 'sub-mesh'. Transform by Trans, pointwise.
#macro MakePyramid(Pig, Trans)
  //Pyramid vertices
  #local Apex = vtransform(y, Trans);
  #local Base = array[4]{-x, z, x, -z};
  #local I = 0;
  #while (I < 4)
    #local Base[I] = vtransform(Base[I], Trans);
    #local I = I + 1;
  #end

  #local T1 = texture{pigment{Pig}finish{specular .5}transform Trans}

  //Make pyramid sides
  #local I = 0;
  #while (I < 4)
    triangle {
      Apex, Base[I], Base[mod(I+1,4)]
      texture {T1}
    }
    #local I = I + 1;
  #end
#end

//make a patch of 'sub-meshes' as a single mesh, in a checkered layout,
//so patches can be overlapped pairwise
#macro MakePatch(F)
mesh{
  #local I=0;
  #while(I < subCount)
  #local J=mod(I, 2);
  #while(J < subCount)
    //Create submesh transform
    #local Trans = transform{
      rotate 45*y
      scale sqrt(.5)/subCount
      translate (<J, 0, I> - .5*<1, 0, 1>*(subCount-1))/subCount
    }

    //Create submesh pigment
    #local C = GetColour((F?I:subCount-1-J), (F?J:I));
    #local CMap = colour_map{[.4 C][.5 rgb F][.6 C]}
    #local Pig = pigment{radial frequency 4 colour_map{CMap}}
    //#local Pig = pigment{bozo scale 1/subCount colour_map{CMap}}
    //#local Pig = C;

    MakePyramid(Pig, Trans)
    #local J = J + 2;
  #end
  #local I = I + 1;
  #end
  scale subCount/(1+subCount)
}
#end

//Create 2 patches
#declare patchM = 2;
#declare Patch = array[patchM];
#declare Patch[0] = MakePatch(0);
#declare Patch[1] = MakePatch(1);

//The group of transforms of a square. 'Even' transforms first.
#declare SqTrans = array[8]
{
  transform{},                                  // 0 ...  I
  transform{rotate 90*y scale <-1, 1, 1>},      // 5 R.X  RX
  transform{rotate 90*y scale < 1, 1,-1>},      // 6 RZ.  RZ
  transform{rotate 180*y},                      // 3 .ZX  R^2

  transform{rotate 90*y},                       // 4 R..  R
  transform{scale <-1, 1, 1>},                  // 1 ..X  X
  transform{scale < 1, 1,-1>},                  // 2 .Z.  Z
  transform{rotate -90*y},                      // 7 RZX  R^3
}

//---Scene-----------------------------------

//place overlapping pairs of patches
#if(1 & (patchCount = 4))                   //show all combinations
  union {
    #declare I=0;
    #while(I < patchCount)
    #declare J=0;
    #while(J < patchCount)
      object {
        Patch[0]
        transform SqTrans[I]                //do an even transform
        translate <I, 0, J>
      }
      object {
        Patch[1]
        transform SqTrans[J+4]              //do an odd transform
        translate <I, 0, J>
      }
      #declare J = J + 1;
    #end
    #declare I = I + 1;
    #end

    translate -0.5*<1, 0, 1>*(patchCount-1)
  }
#else                                       //show random combinations
  union {
    #declare I=0;
    #while(I < patchCount)
    #declare J=0;
    #while(J < patchCount)
      object {
        Patch[RI(patchM)]
        transform SqTrans[RI(4)]            //do an even transform
        translate <I, 0, J>
      }
      object {
        Patch[RI(patchM)]
        transform SqTrans[RI(4)+4]          //do an odd transform
        translate <I, 0, J>
      }
      #declare J = J + 1;
    #end
    #declare I = I + 1;
    #end

    translate -0.5*<1, 0, 1>*(patchCount-1)
  }
#end

background{rgb .5}

//camera {location patchCount*<-1, 2, -3>*.52 look_at .3*y angle 40}
//forward
camera {orthographic location y*patchCount*2.5 look_at 0 angle 30}
//overhead

light_source {<10, 40, -20> rgb 1}

//-----------------------------------------------------------------------------


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.